﻿/*****************************************介绍*****************************************
 * 作者：24531
 * 创建时间：2025-09-13 19:37:28
 * 功能：等级数据资源缓存
**************************************************************************************/

using Game.Framework;
using Game.Framework.Utility;
using Game.UI.LoadingPanel;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class AssetCache
{
    // 缓存指定等级的所有缩略图
    public static void CacheSmallImgs(GameDataModel.Level levelData, Action complate, bool isNew = true)
    {
        var cfg = BaseDataMgr.Instance.Cfg;
        Dictionary<int, int> dict = new Dictionary<int, int>();
        List<AssetItemReq> items = new List<AssetItemReq>();
        var tags = cfg.server.tags;
        var lvTag = levelData.level <= cfg.level.level_data.Length ? cfg.level.level_data[levelData.level - 1].tag : cfg.level.other_level.tag;
        for (int i = 0; i < lvTag.Length; i++)
        {
            if (dict.ContainsKey(lvTag[i]))
                dict[lvTag[i]]++;
            else
                dict.Add(lvTag[i], 1);
        }

        foreach (var info in dict)
        {
            var tagInfo = tags[info.Key];
            AssetItemReq item = new AssetItemReq()
            {
                tag = tagInfo.key,
                num = info.Value,
                sign = tagInfo.sign,
                needNew = isNew
            };
            items.Add(item);
        }

        ReqServerAssets(items, data =>
        {
            string json = CryptoUtils.AesDecrypt(System.Text.Encoding.UTF8.GetString(data));
            LogManager.Log($"data:{json}", "请求资源接口");
            JObject obj = JObject.Parse(json);
            if (obj["code"].Value<int>() != 1)
                LogManager.LogError($"请求接口成功，但结果失败：{json}", "请求资源接口");
            else
            {
                try
                {
                    var urls = obj["data"]["urls"];
                    Dictionary<string, int> handle = new Dictionary<string, int>();
                    for (int i = 0; i < lvTag.Length; i++)
                    {
                        var tag = tags[lvTag[i]].key;
                        JArray tagInfo = urls[tag].Value<JArray>();
                        if (handle.ContainsKey(tag))
                            handle[tag]++;
                        else
                            handle.Add(tag, 0);
                        var item = tagInfo[handle[tag]];
                        if (levelData.assetsInfo == null)
                            levelData.assetsInfo = new List<GameDataModel.AssetInfo>();
                        levelData.assetsInfo.Add(new GameDataModel.AssetInfo()
                        {
                            id = item["id"].Value<int>(),
                            type = EAssetType.Img,
                            rawUrl = item["l"].ToString(),
                            smallUrl = item["s"].ToString(),
                        });
                    }

                    // 真正开始缓存图片
                    int cachedNum = 0;
                    for (int i = 0; i < levelData.assetsInfo.Count; i++)
                    {
                        var info = levelData.assetsInfo[i];
                        AssetCacheServer.Instance.CacheSprite(info.type, info.id, info.smallUrl, complate: sprite =>
                        {
                            cachedNum++;
                            if (cachedNum == levelData.assetsInfo.Count)
                                complate?.Invoke();
                        });
                    }
                }
                catch (Exception e)
                {
                    LogManager.LogError($"请求接口成功，code也等于1，但解析数据时出错：{json}", "请求资源接口", "请求多个资源");
                    CacheSmallImgs(levelData, complate, false);
                }
            }
        }, err =>
        {
            LogManager.LogError($"请求接口失败：{err}", "请求资源接口", "请求多个资源");
            CacheSmallImgs(levelData, complate, isNew);
        });
    }

    // 缓存指定的等的单个缩略图
    public static void CacheSingleSmallImg(GameDataModel.Level levelData, int idx, Action<bool> complate, bool isNew = true)
    {
        var cfg = BaseDataMgr.Instance.Cfg;
        var tags = cfg.server.tags;
        var lvTag = levelData.level <= cfg.level.level_data.Length ? cfg.level.level_data[levelData.level - 1].tag : cfg.level.other_level.tag;
        var item = new AssetItemReq()
        {
            tag = tags[lvTag[idx]].key,
            num = 1,
            sign = tags[lvTag[idx]].sign,
            needNew = isNew
        };

        ReqServerAssets(new List<AssetItemReq>() { item }, data =>
        {
            string json = CryptoUtils.AesDecrypt(System.Text.Encoding.UTF8.GetString(data));
            JObject obj = JObject.Parse(json);
            if (obj["code"].Value<int>() != 1)
            {
                LogManager.LogError($"请求接口成功，但结果失败：{json}", "请求资源接口");
                complate?.Invoke(false);
            }
            else
            {
                try
                {
                    var urls = obj["data"]["urls"];
                    var info = urls[item.tag].Value<JArray>()[0];
                    levelData.assetsInfo[idx].id = info["id"].Value<int>();
                    levelData.assetsInfo[idx].type = EAssetType.Img;
                    levelData.assetsInfo[idx].rawUrl = info["l"].ToString();
                    levelData.assetsInfo[idx].smallUrl = info["s"].ToString();
                    LogManager.Log($"data:{json}", "请求资源接口", "请求单个资源");

                    // 真正开始缓存图片
                    AssetCacheServer.Instance.CacheSprite(levelData.assetsInfo[idx].type, levelData.assetsInfo[idx].id, levelData.assetsInfo[idx].smallUrl, complate: sprite =>
                    {
                        complate?.Invoke(sprite != null);
                    });
                }
                catch (Exception e)
                {
                    LogManager.LogError($"请求接口成功，code也等于1，但解析数据时出错：{json}", "请求资源接口");
                    CacheSingleSmallImg(levelData, idx, complate, false); // 如果情趣成功，但没有数据，表示没图了，这里就重复请求旧图而不是新图
                }
            }
        }, err =>
        {
            LogManager.LogError($"请求接口失败：{err}", "请求资源接口");
            CacheSingleSmallImg(levelData, idx, complate, isNew);
        });
    }

    // 缓存指定城市的所有缩略图
    public static void CacheSmallImgs(GameDataModel.City cityData, Action complate, bool isNew = true)
    {
        var cityCfg = BaseDataMgr.Instance.GetCountryCfg(cityData.countryName)[cityData.name];
        Dictionary<int, int> dict = new Dictionary<int, int>();
        List<AssetItemReq> items = new List<AssetItemReq>();
        var tags = BaseDataMgr.Instance.Cfg.server.tags;
        var lvTag = cityCfg.tag;
        for (int i = 0; i < lvTag.Length; i++)
        {
            if (dict.ContainsKey(lvTag[i]))
                dict[lvTag[i]]++;
            else
                dict.Add(lvTag[i], 1);
        }

        foreach (var info in dict)
        {
            var tagInfo = tags[info.Key];
            AssetItemReq item = new AssetItemReq()
            {
                tag = tagInfo.key,
                num = info.Value,
                sign = tagInfo.sign,
                needNew = isNew
            };
            items.Add(item);
        }

        ReqServerAssets(items, data =>
        {
            string json = CryptoUtils.AesDecrypt(System.Text.Encoding.UTF8.GetString(data));
            LogManager.Log($"data:{json}", "请求资源接口");
            JObject obj = JObject.Parse(json);
            if (obj["code"].Value<int>() != 1)
                LogManager.LogError($"请求接口成功，但结果失败：{json}", "请求资源接口");
            else
            {
                try
                {
                    var urls = obj["data"]["urls"];
                    Dictionary<string, int> handle = new Dictionary<string, int>();
                    for (int i = 0; i < lvTag.Length; i++)
                    {
                        var tag = tags[lvTag[i]].key;
                        JArray tagInfo = urls[tag].Value<JArray>();
                        if (handle.ContainsKey(tag))
                            handle[tag]++;
                        else
                            handle.Add(tag, 0);
                        var item = tagInfo[handle[tag]];
                        if (cityData.imgInfos == null)
                            cityData.imgInfos = new List<GameDataModel.ImgData>();
                        var itemData = new GameDataModel.AssetInfo()
                        {
                            id = item["id"].Value<int>(),
                            type = EAssetType.Img,
                            rawUrl = item["l"].ToString(),
                            smallUrl = item["s"].ToString(),
                        };
                        cityData.imgInfos.Add(new GameDataModel.ImgData() { assetsInfo = itemData });
                    }

                    // 真正开始缓存图片
                    int cachedNum = 0;
                    for (int i = 0; i < cityData.imgInfos.Count; i++)
                    {
                        var info = cityData.imgInfos[i].assetsInfo;
                        AssetCacheServer.Instance.CacheSprite(info.type, info.id, info.smallUrl, complate: sprite =>
                        {
                            cachedNum++;
                            if (cachedNum == cityData.imgInfos.Count)
                                complate?.Invoke();
                        });
                    }
                }
                catch (Exception e)
                {
                    LogManager.LogError($"请求接口成功，code也等于1，但解析数据时出错：{json}", "请求资源接口", "请求多个资源");
                    CacheSmallImgs(cityData, complate, false);
                }
            }
        }, err =>
        {
            LogManager.LogError($"请求接口失败：{err}", "请求资源接口", "请求多个资源");
            CacheSmallImgs(cityData, complate, isNew);
        });
    }

    public static void ReqServerAssets(List<AssetItemReq> datas, UnityAction<byte[]> succHandle, UnityAction<string> failHandle)
    {
        JArray items = new JArray();
        for (int i = 0; i < datas.Count; i++)
        {
            JObject item = new JObject
            {
                {"tg", datas[i].tag },
                {"n", datas[i].num },
                {"s", CryptoUtils.StringToMD5(datas[i].sign) },
                {"in", datas[i].needNew },
            };
            items.Add(item);
        }

        var heards = new JObject
        {
            {"Content-Type", "application/json" },
            {"Product", GlobalFixedString.PRODUCT_NAME }
        };
        var param = new JObject
        {
            {"version", Application.version },
            {"uid", GameDataMgr.Instance.Uid.ToString() },
            {"items", items },
        };

        CommonMono.NetPostData data = new CommonMono.NetPostData()
        {
            url = $"{GlobalFixedString.REQ_URL}/{BaseDataMgr.Instance.Cfg.server.url}",
            reqHeaders = heards,
            reqParams = param,
            callBack = succHandle,
            failCallBack = failHandle,
            isEncrypt = true
        };
        CommonMono.Instance.SendPostReqest(data);
    }
}